package com.alpaak.common.utils.log;

import com.alpaak.common.utils.DateUtil;
import org.apache.log4j.Logger;

import java.io.Serializable;
import java.util.Date;

/**
 * @ClassName: LogUtil
 * @Description: 基于log4j封装的日志输出工具类
 * @author: FengWenJu
 * @date: 2017年11月3日 上午10:49:48
 */
public class Log4jUtil implements Serializable {
	private static final long serialVersionUID = -6366640992160757401L;
	//默认编码,用来方便查找
	private static final int DEBUG_LOG = 99999;
	//输出日志的类的名称和日志内容的分割符
	private static final String SP_CHAR = ": ";
	//日志默认输出类名称
	private static final String FLAG_LOGGER = "LOG4J";
	//日志级别分类
	private static final String FLAG_DEBUG = "debug";
	private static final String FLAG_INFO = "info";
	private static final String FLAG_ERROR = "error";

	static Logger logger = Logger.getLogger(FLAG_LOGGER);
	
	/**
	 * @Title: debug  
	 * @Description: 日志debug输出
	 * @param @param msg 字符串日志消息  
	 * @return void    
	 * @throws
	 */
	public static void debug(String msg) {
		debug(null, msg);
	}

	/**
	 * @Title: debug  
	 * @Description: 日志debug输出
	 * @param @param clazz 日志输出的所在类本身
	 * @param @param msg   字符串日志消息    
	 * @return void    
	 * @throws
	 */
	public static void debug(Class<?> clazz, String msg) {
		log(clazz, FLAG_DEBUG, buildMsg(DEBUG_LOG, msg, null));
	}

	/**
	 * @Title: info  
	 * @Description: 日志info输出
	 * @param @param msg  字符串日志消息       
	 * @return void    
	 * @throws
	 */
	public static void info(String msg) {
		info(null, msg);
	}

	/**
	 * @Title: info  
	 * @Description: 日志info输出
	 * @param @param clazz 日志输出的所在类本身
	 * @param @param msg   字符串日志消息         
	 * @return void    
	 * @throws
	 */
	public static void info(Class<?> clazz, String msg) {
		log(clazz, FLAG_INFO, buildMsg(DEBUG_LOG, msg, null));
	}

	/**
	 * @Title: error  
	 * @Description: 日志error输出
	 * @param @param msg 字符串日志消息         
	 * @param @param e   错误异常  
	 * @return void    
	 * @throws
	 */
	public static void error(String msg, Throwable e) {
		error(null, msg, e);
	}

	/**
	 * @Title: error  
	 * @Description: 日志error输出
	 * @param @param clazz 日志输出的所在类本身
	 * @param @param msg   字符串日志消息      
	 * @param @param e     错误异常  
	 * @return void    
	 * @throws
	 */
	public static void error(Class<?> clazz, String msg, Throwable e) {
		log(clazz, FLAG_ERROR, buildMsg(DEBUG_LOG, msg, e));
	}

	/**
	 * @Title: log  
	 * @Description: 日志公用输出私有方法
	 * @param @param clazz  日志输出的所在类本身
	 * @param @param type	日志级别   
	 * @param @param msg    日志消息封装对象 
	 * @return void    
	 * @throws
	 */
	private static void log(Class<?> clazz, String type, LogMsg msg) {
		String preClassName = getClassName(clazz);
		if (!"".equals(preClassName)) {
			preClassName = preClassName + SP_CHAR;
		}
		if (msg.getMessage() == null)
			msg.setMessage("");

		if (FLAG_DEBUG.equals(type)) {
			logger.debug(preClassName + msg.getMessage());

		} else if (FLAG_INFO.equals(type)) {
			logger.info(preClassName + msg.getMessage());

		} else if (FLAG_ERROR.equals(type)) {
			if (msg.getException() == null)
				logger.error(preClassName + msg.toString());
			else
				logger.error(preClassName + msg.toString(), msg.getException());
		} else
			System.out.println("["
					+ FLAG_LOGGER
					+ DateUtil.converToString(new Date(), "yyyy-MM-dd HH:mm:ss")
					+ "] " + getClassName(clazz, msg) + " - " + msg.getMessage());
	}
	
	private static String getClassName(Class<?> clazz){
		String className = null;
		if(clazz!=null){
			className = clazz.getName();
		}
		return className == null ? "" : className;
	}

	private static String getClassName(Class<?> clazz, LogMsg msg) {
		String className = null;
		if (clazz == null) {
			StackTraceElement ste = getStackTraceElement(msg.getException());
			msg.setLocation(ste.toString());
			className = ste.getClassName();
		} else {
			className = getClassName(clazz);
		}
		return className == null ? "" : className;
	}

	private static LogMsg buildMsg(int code, String msg, Throwable e) {
		String dateStr = DateUtil.converToString(new Date(), "yyyy-MM-dd HH:mm:ss");
		LogMsg myMsg = new LogMsg();
		myMsg.setDateTime(dateStr);
		myMsg.setCode(code);
		myMsg.setMessage(msg);
		myMsg.setException(e);
		return myMsg;
	}

	/**
	 * 通过异常，获取报错发生的类名称
	 */
	private static StackTraceElement getStackTraceElement(Throwable e) {
		StackTraceElement[] element = null;
		if (e == null) {
			element = new Exception().getStackTrace();
		} else if (e.getCause() == null)
			element = e.getStackTrace();
		else {
			element = e.getCause().getStackTrace();
		}

		for (int i = 0; i < element.length; i++) {
			String className = element[i].getClassName();
			if (className.indexOf("Log4jUtil") < 0 
					&& className.indexOf("com.ewell") >= 0)
				return element[i];
		}
		return element[1];
	}

}
